package cur.tool.common.table;

import cur.nature.framework.core.log.LOG;
import cur.nature.framework.core.util.StringUtil;
import cur.nature.tinyorm.core.annotation.Column;
import cur.nature.tinyorm.core.annotation.Table;
import cur.nature.tinyorm.core.template.DefaultJdbcTemplate;
import org.reflections.Reflections;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class Mysql {
    private DefaultJdbcTemplate template;

    public Mysql(final DefaultJdbcTemplate template) {
        this.template = template;
    }

    public String createTable(final String packages) {
        LOG.info("mysql 开始检测库表");
        try {
            Reflections reflections = new Reflections(packages);
            Set<Class<?>> set = reflections.getTypesAnnotatedWith(Table.class);
            for (Class<?> aClass : set) {
                List<String> columnList = new ArrayList<>();
                List<String> idList = new ArrayList<>();
                Table table = aClass.getAnnotation(Table.class);
                String tempStr = null;
                // 判断表是否存在
                try {
                    tempStr = template.queryForObject(
                            "SELECT concat(count(0),'_') as name FROM '" + table.name() + "'", String.class);
                } catch (Exception ex) {
                }
                if (StringUtil.isNotEmpty(tempStr)) {
                    LOG.info("表 : " + table.name() + " 已存在。");
                    continue;
                }
                // 字段处理
                List<Field> fieldList = getField(aClass);
                for (Field field : fieldList) {
                    Column fieldInfo = field.getAnnotation(Column.class);
                    if (fieldInfo != null) {
                        // 处理字段名
                        String columnName = fieldInfo.name();
                        // 主键
                        if (fieldInfo.isPK()) {
                            idList.add(columnName);
                        }
                        // 处理类型
                        String typeStr = getType(field.getType(), fieldInfo);
                        // 是否为空
                        String isNull = fieldInfo.isNull() ? " NULL " : " NOT NULL ";
                        // 拼接字段
                        String str = "`" + columnName + "` " + typeStr + " CHARACTER SET utf8mb4 COLLATE utf8mb4_bin " + isNull + " COMMENT '" + fieldInfo.desc() + "'";
                        columnList.add(str);
                    }
                }
                // 处理主键
                String idStr = "PRIMARY KEY (" + idList.stream().collect(Collectors.joining(",")) + ") USING BTREE ";
                columnList.add(idStr);
                // 拼接sql
                String sql = "CREATE TABLE IF NOT EXISTS `" + table.name()
                        + "` ( \n" + columnList.stream().collect(Collectors.joining(",\n")) + " )";
                sql += " ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '" + table.desc() + "' ROW_FORMAT = Dynamic ";

                LOG.info("创建表: " + table.name());
                LOG.info(sql);
                // 执行创建表
                template.execute(sql);
            }
        } catch (Exception e) {
            e.printStackTrace();
            LOG.error("创建表失败, ", e);
            return "fail";
        }

        return "success";
    }

    public String getType(Class<?> targetClass, Column fieldInfo) {
        int len = fieldInfo.len();
        int point = fieldInfo.point();

        //处理类型
        if (String.class == targetClass) {
            return "varchar(" + len + ")";
        } else if (short.class == targetClass || Short.class.isAssignableFrom(targetClass)) {
            return "tinyint(" + len + ")";
        } else if (int.class == targetClass || Integer.class.isAssignableFrom(targetClass)) {
            return "int(" + len + ")";
        } else if (long.class == targetClass || Long.class.isAssignableFrom(targetClass)) {
            return "bigint(" + len + ")";
        } else if (float.class == targetClass || Float.class.isAssignableFrom(targetClass)) {
            return "float(" + len + ", " + point + " )";
        } else if (double.class == targetClass || Double.class.isAssignableFrom(targetClass)) {
            return "double(" + len + ", " + point + " )";
        } else if (BigDecimal.class.isAssignableFrom(targetClass)) {
            return "decimal(" + len + ", " + point + " )";
        } else if (Date.class.isAssignableFrom(targetClass)) {
            return "datetime(" + len + ")";
        } else if (Timestamp.class == targetClass || ZonedDateTime.class == targetClass) {
            return "datetime(" + len + ")";
        } else {
            return null;
        }
    }

    // 获取所有字段
    public List<Field> getField(Class<?> clazz) {
        // 获取字段
        List<Field> list = new ArrayList<>();
        Field[] fields = clazz.getDeclaredFields();
        list.addAll(Arrays.asList(fields));
        // 获取父类字段
        Class<?> superClazz = clazz.getSuperclass();
        if (superClazz != null) {
            Field[] superFields = superClazz.getDeclaredFields();
            list.addAll(Arrays.asList(superFields));
        }
        return list;
    }
}
